/* Copyright 2018-2020,2022,2023 NXP.
 *
 * NXP Confidential. This software is owned or controlled by NXP and may only be
 * used strictly in accordance with the applicable license terms. By expressly
 * accepting such terms or by downloading,installing, activating and/or otherwise
 * using the software, you are agreeing that you have read,and that you agree to
 * comply with and are bound by, such license terms. If you do not agree to be
 * bound by the applicable license terms, then you may not retain, install, activate
 * or otherwise use the software.
 *
 */

#include "UwbApi.h"
#include "PrintUtility.h"
#include "AppConfigParams.h"
#include "UwbApi_Utility.h"
#include <uwa_api.h>
#include "phNxpLogApis_UwbApi.h"
#include "phOsalUwb.h"
#include "phNxpUwbConfig.h"
#include "UwbAdaptation.h"
#include "uwb_hal_int.h"
#include "UwbCoreSDK_Internal.h"
#include "UwbApi_Proprietary_Internal.h"
#include "uci_ext_defs.h"
#include "uci_test_defs.h"
#include "uwa_dm_int.h"
#include "phNxpLogApis_UwbApi.h"
#include "UwbApi_Internal.h"
#include "uwbiot_ver.h"
#include "uwb_types.h"
#include "SR040_RadioCfg_CRCTable.h"
#include "UwbApi_Proprietary.h"

/*TLV COUNT 1 BYTE*/
#define LUT_TLV_COUNT_LEN 0x01
/*LUT_SEL 1 BYTE*/
#define LUT_TLV_SEL_LEN 0x01
/*LENGHT OF CRC  1 BYTE*/
#define LUT_CRC_LEN 0x01

/**
 * @brief  Structure indicates the Radio config crc elements.
 */
typedef struct RadioConfigCrcTable
{
    uint8_t index;
    uint16_t crc;
} RadioConfigCrcTable_t;

/** Local function prototypes */
static tUWBAPI_STATUS UwbApi_StopTestMode_RAW();

EXTERNC tUWBAPI_STATUS UwbApi_GetDeviceInfo(phUwbDevInfo_t *pdevInfo)
{
    tUWBAPI_STATUS status;
    NXPLOG_UWBAPI_D("%s: enter; ", __FUNCTION__);
    if (uwbContext.isUfaEnabled == FALSE) {
        NXPLOG_UWBAPI_E("%s: UWB device is not initialized", __FUNCTION__);
        return UWBAPI_STATUS_NOT_INITIALIZED;
    }

    if (pdevInfo == NULL) {
        NXPLOG_UWBAPI_E("%s: pdevInfo is NULL", __FUNCTION__);
        return UWBAPI_STATUS_INVALID_PARAM;
    }

    status = getDeviceInfo();

    if (status == UWBAPI_STATUS_OK) {
        if (parseDeviceInfo(pdevInfo) == FALSE) {
            NXPLOG_UWBAPI_E("%s: Parsing Device Information Failed", __FUNCTION__);
            status = UWBAPI_STATUS_FAILED;
        }
    }
    else if (status == UWBAPI_STATUS_TIMEOUT) {
        NXPLOG_UWBAPI_E("%s: Parsing Device Information Timed Out", __FUNCTION__);
    }
    else {
        NXPLOG_UWBAPI_E("%s: Parsing Device Information failed", __FUNCTION__);
        status = UWBAPI_STATUS_FAILED;
    }

    NXPLOG_UWBAPI_D("%s: exit status %d", __FUNCTION__, status);
    return status;
}

EXTERNC tUWBAPI_STATUS UwbApi_SuspendDevice()
{
    tUWBAPI_STATUS status;
    NXPLOG_UWBAPI_D("%s: Enter", __FUNCTION__);

    if (uwbContext.isUfaEnabled == FALSE) {
        NXPLOG_UWBAPI_E("%s: UWB device is not initialized", __FUNCTION__);
        return UWBAPI_STATUS_NOT_INITIALIZED;
    }

    sep_SetWaitEvent(UWA_DM_PROP_SUSPEND_DEVICE_RSP_ENVT);
    status = sendUciCommandAndWait(UWA_DM_API_SUSPEND_DEVICE_EVENT, 0, NULL);
    if (status == UWBAPI_STATUS_OK) {
        phOsalUwb_Delay(200);
        NXPLOG_UWBAPI_D("%s: Suspend Command successful", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_TIMEOUT) {
        NXPLOG_UWBAPI_E("%s: Suspend Command Timed Out", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_HPD_WAKEUP) {
        NXPLOG_UWBAPI_W("%s: Device Woken up from HPD", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_LOW_POWER_ERROR) {
        NXPLOG_UWBAPI_E("%s: Device having very low battery power", __FUNCTION__);
    }
    else {
        NXPLOG_UWBAPI_E("%s: Suspend Command failed", __FUNCTION__);
    }

    NXPLOG_UWBAPI_D("%s: Exit", __FUNCTION__);
    return status;
}

EXTERNC tUWBAPI_STATUS UwbApi_PropSR040_SetDPDTimeout(uint16_t dpd_timeout)
{
    uint8_t dpdCommand[] = {0x20,           // GID of Core_Set_Config_cmd
        0x04,                               // OID of Core_Set_Config_cmd
        0x00,                               // RFU
        0x05,                               // PayloadLength
        0x01,                               // NoOfParameters
        UCI_EXT_PARAM_ID_DPD_ENTRY_TIMEOUT, // HPD_TIMEOUT_ID
        0x02,                               // Length Of HPD_TIME_OUT_VALUE
        (uint8_t)(dpd_timeout),
        (uint8_t)(dpd_timeout >> 8)};
    uint8_t dpdRsp[10]   = {0};
    uint16_t length      = sizeof(dpdRsp);

    tUWBAPI_STATUS status = UwbApi_SendRawCommand(dpdCommand, sizeof(dpdCommand), dpdRsp, &length);
    if (status == UWBAPI_STATUS_OK) {
        status = dpdRsp[4];
    }
    return status;
}

EXTERNC tUWBAPI_STATUS UwbApi_PropSR040_SetHPDTimeout(uint16_t hpd_timeout)
{
    uint8_t hpdCommand[] = {0x20,           // GID of Core_Set_Config_cmd
        0x04,                               // OID of Core_Set_Config_cmd
        0x00,                               // RFU
        0x05,                               // PayloadLength
        0x01,                               // NoOfParameters
        UCI_EXT_PARAM_ID_HPD_ENTRY_TIMEOUT, // HPD_TIMEOUT_ID
        0x02,                               // Length Of HPD_TIME_OUT_VALUE
        (uint8_t)(hpd_timeout),
        (uint8_t)(hpd_timeout >> 8)};
    uint8_t hpdRsp[10]   = {0};
    uint16_t length      = sizeof(hpdRsp);

    tUWBAPI_STATUS status = UwbApi_SendRawCommand(hpdCommand, sizeof(hpdCommand), hpdRsp, &length);
    if (status == UWBAPI_STATUS_OK) {
        status = hpdRsp[4];
    }
    return status;
}
EXTERNC tUWBAPI_STATUS UwbApi_SessionNvmManage(esessionNvmManage sesNvmManageTag, uint32_t sessionid)
{
    tUWBAPI_STATUS status;
    uint16_t cmdLen;
    NXPLOG_UWBAPI_D("%s: Enter", __FUNCTION__);

    if (uwbContext.isUfaEnabled == FALSE) {
        NXPLOG_UWBAPI_E("%s: UWB device is not initialized", __FUNCTION__);
        return UWBAPI_STATUS_NOT_INITIALIZED;
    }
    sep_SetWaitEvent(UWA_DM_SESSION_NVM_PAYLOAD_RSP_EVENT);
    cmdLen = serializeSessionNvmPayload(sesNvmManageTag, sessionid, uwbContext.snd_data);

    if (cmdLen == 0) {
        return UWBAPI_STATUS_INVALID_PARAM;
    }

    status = sendUciCommandAndWait(UWA_DM_API_SESSION_NVM_EVENT, cmdLen, uwbContext.snd_data);
    if (status == UWBAPI_STATUS_OK) {
        NXPLOG_UWBAPI_D("%s: Session NVM Manage Command successful", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_TIMEOUT) {
        NXPLOG_UWBAPI_E("%s: Session NVM Manage Command Timed Out", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_HPD_WAKEUP) {
        NXPLOG_UWBAPI_W("%s: Device Woken up from HPD", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_LOW_POWER_ERROR) {
        NXPLOG_UWBAPI_E("%s: Device having very low battery power", __FUNCTION__);
    }
    else {
        NXPLOG_UWBAPI_E("%s: Session NVM Manage Command failed", __FUNCTION__);
    }

    NXPLOG_UWBAPI_D("%s: Exit", __FUNCTION__);
    return status;
}
EXTERNC tUWBAPI_STATUS UwbApi_StartTestMode(eTestMode testMode, const phTestModeParams *testModeParams)
{
    tUWBAPI_STATUS status;
    static uint8_t isPbfSet = 0;
    NXPLOG_UWBAPI_D("%s: Enter", __FUNCTION__);

    uint16_t commandLength = 0;
    uint8_t *pCommand      = NULL;
    uint16_t extTagLength  = 0;
    uint8_t extTagId       = 0;
    uint16_t frameLength   = 0;
    uint8_t *pExtData      = NULL;

    if (uwbContext.isUfaEnabled == FALSE) {
        NXPLOG_UWBAPI_E("%s: UWB device is not initialized", __FUNCTION__);
        return UWBAPI_STATUS_NOT_INITIALIZED;
    }

    if (testMode == RECEIVE_MODE || testMode == TRANSMIT_MODE) {
        if (testModeParams == NULL) {
            NXPLOG_UWBAPI_E("%s: testModeParams is NULL", __FUNCTION__);
            return UWBAPI_STATUS_INVALID_PARAM;
        }

        if (testMode == TRANSMIT_MODE) {
            /*common parameter for TX & RX mode for extended psdu logging*/
            if (testModeParams->transmitModeParams.psduData == NULL ||
                testModeParams->transmitModeParams.psduLen == 0) {
                NXPLOG_UWBAPI_E("%s: psduData is NULL or psduLen is Zero", __FUNCTION__);
                return UWBAPI_STATUS_INVALID_PARAM;
            }

            if (testModeParams->transmitModeParams.psduLen > MAX_HPRF_PSDU_DATA_PACKET_SIZE) {
                NXPLOG_UWBAPI_E("%s: psduLen is exceeds than limit", __FUNCTION__);
                return UWBAPI_STATUS_INVALID_PARAM;
            }
            if (testModeParams->transmitModeParams.enableLogging == TRUE) {
                // Perform Set App Config to Enable logging while in Transmit Mode
                UwbApi_SetAppConfig(SESSION_ID_RFTEST, TX_PHY_LOGGING_ENABLE, 1);
            }
            if (testModeParams->transmitModeParams.psduLen > BPRF_MAX_PSDU_FRAME_SIZE) {
                /*making pbf bit enable as it is HPRF Mode*/
                isPbfSet = 1;
            }
        }
        else {
            if (testModeParams->receiveModeParams.enableLogging == TRUE) {
                // Perform Set App Config to Enable logging while in Receive Mode
                UwbApi_SetAppConfig(SESSION_ID_RFTEST, RX_PHY_LOGGING_ENABLE, 1);
            }
        }
    }
    sep_SetWaitEvent(UWA_DM_START_TEST_MODE_RSP_EVENT);
    pCommand = uwbContext.snd_data;
    if (formTestModeCommand(testMode, testModeParams, pCommand, &commandLength) == FALSE) {
        return UWBAPI_STATUS_INVALID_PARAM;
    }

    if ((testMode == TRANSMIT_MODE) && (testModeParams->transmitModeParams.psduLen > BPRF_MAX_PSDU_FRAME_SIZE)) {
        /*Test start command for ext psdu*/
        status = sendUciCommand(UWA_DM_START_TEST_MODE_EVENT, commandLength, uwbContext.snd_data, isPbfSet);
        if (status == UWBAPI_STATUS_OK) {
            status = UWBAPI_STATUS_OK;
            NXPLOG_UWBAPI_D("%s: Test Mode Cmd successful", __FUNCTION__);
        }
        else
            goto exit;

        commandLength = 0;
        pCommand      = uwbContext.snd_data;
        extTagId      = UCI_EXT_TEST_MODE_ID_EXTENDED_PSDU_FRAME1;
        frameLength   = testModeParams->transmitModeParams.psduLen;
        pExtData      = (uint8_t *)testModeParams->transmitModeParams.psduData;

        while (frameLength) {
            /* perform  chunking and transfer data*/
            if (frameLength > EXTENDED_PSDU_FRAME_MAX_SIZE_HPRF) {
                extTagLength = EXTENDED_PSDU_FRAME_MAX_SIZE_HPRF;
                isPbfSet     = 1;
                frameLength  = frameLength - EXTENDED_PSDU_FRAME_MAX_SIZE_HPRF;
            }
            else {
                extTagLength = frameLength;
                isPbfSet     = 0;
                frameLength  = 0;
            }

            /*final command length for ext frame*/
            commandLength = 1 + UCI_EXT_TEST_MODE_ID_EXTENDED_PSDU_FRAME_LEN + extTagLength;
            /*forming the ext psdu command*/
            UWB_UINT8_TO_STREAM(pCommand, extTagId);
            UWB_UINT8_TO_STREAM(pCommand, extTagLength);
            UWB_ARRAY_TO_STREAM(pCommand, pExtData, extTagLength);

            /*send ext psdu command with pbf bit*/
            status = sendUciCommand(UWA_DM_START_TEST_MODE_EVENT, commandLength, uwbContext.snd_data, isPbfSet);
            if (status == UWBAPI_STATUS_OK) {
                status = UWBAPI_STATUS_OK;
                NXPLOG_UWBAPI_D("%s: Test Mode Cmd successful", __FUNCTION__);
            }
            else
                goto exit;

            extTagId = extTagId + 1;            /*Incrementing tag ID*/
            pExtData = pExtData + extTagLength; /*incrementing data pointer */
            pCommand = uwbContext.snd_data;     /*reassigning the pcommand buff */
        }
    }
    else {
        status = sendUciCommandAndWait(UWA_DM_START_TEST_MODE_EVENT, commandLength, uwbContext.snd_data);
    }

exit:
    if (status == UWBAPI_STATUS_OK) {
        status = UWBAPI_STATUS_OK;
        NXPLOG_UWBAPI_D("%s: Test Mode Cmd successful", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_TIMEOUT) {
        NXPLOG_UWBAPI_D("%s: Test Mode Command Timed Out", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_HPD_WAKEUP) {
        NXPLOG_UWBAPI_D("%s: Device Woken up from HPD", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_LOW_POWER_ERROR) {
        NXPLOG_UWBAPI_E("%s: Device having very low battery power", __FUNCTION__);
    }
    else {
        NXPLOG_UWBAPI_E("%s: Test Mode Command failed %d", __FUNCTION__, status);
        status = UWBAPI_STATUS_FAILED;
    }

    NXPLOG_UWBAPI_D("%s: Exit", __FUNCTION__);
    return status;
}

/* Since we dont' get NTF 2.2.x onwards, add a local RAW API to send RAW APDU
 *
 * Temporary FIX, until it gets handled cleanly at MW level.
 */
static tUWBAPI_STATUS UwbApi_StopTestMode_RAW()
{
    tUWBAPI_STATUS status;
    uint8_t stop_sr040_test_mode_cmd[] = {0x2E, 0x21, 0x00, 0x00};
    uint8_t stop_sr040_test_mode_rsp[256];
    uint16_t stop_sr040_test_mode_rsp_len = sizeof(stop_sr040_test_mode_rsp);

    status = UwbApi_SendRawCommand(stop_sr040_test_mode_cmd,
        sizeof(stop_sr040_test_mode_cmd),
        stop_sr040_test_mode_rsp,
        &stop_sr040_test_mode_rsp_len);

    if (UWBAPI_STATUS_OK == status && 5 == stop_sr040_test_mode_rsp_len) {
        status = stop_sr040_test_mode_rsp[4];
    }
    else if (status == UWBAPI_STATUS_TIMEOUT) {
        /* Return this status. PCTT APP will handle it appropriately. */
    }
    else if (status == UWBAPI_STATUS_HPD_WAKEUP) {
        NXPLOG_UWBAPI_D("%s: Device Woken up from HPD", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_LOW_POWER_ERROR) {
        NXPLOG_UWBAPI_E("%s: Device having very low battery power", __FUNCTION__);
    }
    else {
        status = UWBAPI_STATUS_FAILED;
    }
    return status;
}

EXTERNC tUWBAPI_STATUS UwbApi_StopTestMode()
{
#if 0
    tUWBAPI_STATUS status;

    NXPLOG_UWBAPI_D("%s: Enter", __FUNCTION__);

    if (uwbContext.isUfaEnabled == FALSE) {
        NXPLOG_UWBAPI_E("%s: UWB device is not initialized", __FUNCTION__);
        return UWBAPI_STATUS_NOT_INITIALIZED;
    }

    sep_SetWaitEvent(UWA_DM_STOP_TEST_MODE_RSP_EVENT);
    status = sendUciCommandAndWait(UWA_DM_STOP_TEST_MODE_EVENT, 0, NULL);
    if (status == UWBAPI_STATUS_OK) {
        if (waitforNotification(EXT_UCI_MSG_TEST_STOP_CMD, UWBD_TEST_MODE_NTF_TIMEOUT) == UWBAPI_STATUS_OK) {
            NXPLOG_UWBAPI_D("%s: Test Mode Cmd successful", __FUNCTION__);
        }
        else {
            NXPLOG_UWBAPI_D("%s: Test Mode Ntf Wait Failed", __FUNCTION__);
        }
    }
    else if (status == UWBAPI_STATUS_TIMEOUT) {
        NXPLOG_UWBAPI_E("%s: Test Mode Command Timed Out", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_HPD_WAKEUP) {
        NXPLOG_UWBAPI_E("%s: Device Woken up from HPD", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_LOW_POWER_ERROR) {
        NXPLOG_UWBAPI_E("%s: Device having very low battery power", __FUNCTION__);
    }
    else {
        NXPLOG_UWBAPI_E("%s: Test Mode Command failed", __FUNCTION__);
        status = UWBAPI_STATUS_FAILED;
    }

    NXPLOG_UWBAPI_D("%s: Exit", __FUNCTION__);

    int retryCount = 5;
    status         = UwbApi_StopTestMode_RAW();
    while (retryCount-- > 0 && status != UWBAPI_STATUS_OK) {
        LOG_W("# Stop Test Retry:%d, status=0x%X", retryCount, status);
        status = UwbApi_StopTestMode_RAW();
    }
#endif

    return UwbApi_StopTestMode_RAW();
}

EXTERNC tUWBAPI_STATUS UwbApi_SetCalibration(
    eCalibParam paramId, phCalibrationData *pCalibData, phCalibrationStatus_t *calibResp)
{
    tUWBAPI_STATUS status;
    uint8_t *pSetCalibrationCmd = NULL;
    uint16_t commandLength      = 0;
    NXPLOG_UWBAPI_D("%s: Enter", __FUNCTION__);

    if (uwbContext.isUfaEnabled == FALSE) {
        NXPLOG_UWBAPI_E("%s: UWB device is not initialized", __FUNCTION__);
        return UWBAPI_STATUS_NOT_INITIALIZED;
    }
    if (pCalibData == NULL) {
        NXPLOG_UWBAPI_E("%s: data is invalid", __FUNCTION__);
        return UWBAPI_STATUS_INVALID_PARAM;
    }
    pSetCalibrationCmd = uwbContext.snd_data;
    switch (paramId) {
    case TX_POWER_DIFF:
    case TX_POWER_DIFF_ANT_BOTTOM:
    case FREQ_DIFF:
    case ANTENNA_DELAY:
    case ANTENNA_DELAY_ANT_BOTTOM:
    case CURRENT_LIMIT_VALUE:
    case TX_ADAPTIVE_POWER_CALC:
    case TX_ADAPTIVE_POWER_CALC_ANT_BOTTOM:
    case DDFS_TONE_VALUES:
    case TEMP_COMPENS_FLAG:
    case TEMPERATURE_SOURCE:
    case THERMISTOR_RP:
    case LUT_XTAL:
    case LUT_THERMISTER:
    case DPD_TIMER_PENALTY_US:
    case TRIM_POWER_CTRL_PREAMBLE_10:
    case TRIM_POWER_CTRL_PREAMBLE_27:
    case WAKEUP_SENSOR_ENABLE:
    case SLOW_BLINK_INTERVAL:
    case TRIM_LOCK:
    case CUSTOM_LUTS_ENBL:
    case LUT_TEMP_RT_OFFSET:
    case LUT_TEMP_RT_SLOPE:
    case TRIM_PREAMBLE_10_27_PAYLOAD_PS_COEFFS_OVERRIDE:
    case MODULE_MAKER_ID:
        formCalibrationCommand(paramId, (void *)pCalibData, pSetCalibrationCmd, &commandLength);
        break;
    default:
        NXPLOG_UWBAPI_E("%s:    Invalid Param ", __FUNCTION__);
        return UWBAPI_STATUS_INVALID_PARAM;
    }
    sep_SetWaitEvent(UWA_DM_SET_CALIB_TRIM_RSP_EVENT);
    status = sendUciCommandAndWait(UWA_DM_SET_CALIB_TRIM_EVENT, commandLength, uwbContext.snd_data);
    if (status == UWBAPI_STATUS_OK) {
        status = waitforNotification(EXT_UCI_MSG_SET_TRIM_VALUES_CMD, UWBD_CALIB_NTF_TIMEOUT);
        if (status == UWBAPI_STATUS_OK) {
            calibResp->status = uwbContext.calibrationStatus.status;
            if (uwbContext.calibrationStatus.status == APPLIED) {
                NXPLOG_UWBAPI_D("%s: Set Calibration notification successful", __FUNCTION__);
            }
            else {
                NXPLOG_UWBAPI_E("%s: Set Calibration notification failed", __FUNCTION__);
            }
        }
        else {
            NXPLOG_UWBAPI_E("%s: Set Calibration notification time out", __FUNCTION__);
        }
    }
    else if (status == UWBAPI_STATUS_TIMEOUT) {
        NXPLOG_UWBAPI_E("%s: Set Calibration Command Timed Out", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_HPD_WAKEUP) {
        NXPLOG_UWBAPI_E("%s: Device Woken up from HPD", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_LOW_POWER_ERROR) {
        NXPLOG_UWBAPI_E("%s: Device having very low battery power", __FUNCTION__);
    }
    else {
        NXPLOG_UWBAPI_E("%s: Set Calibration failed", __FUNCTION__);
        status = UWBAPI_STATUS_FAILED;
    }

    NXPLOG_UWBAPI_D("%s: Exit", __FUNCTION__);
    return status;
}
EXTERNC tUWBAPI_STATUS UwbApi_GetCalibration(eCalibParam paramId, phCalibRespStatus_t *calibResp)
{
    tUWBAPI_STATUS status;
    uint8_t *pGetCalibrationCmd = NULL;
    uint8_t payloadLen          = 2;
    NXPLOG_UWBAPI_D("%s: Enter", __FUNCTION__);

    if (uwbContext.isUfaEnabled == FALSE) {
        NXPLOG_UWBAPI_E("%s: UWB device is not initialized", __FUNCTION__);
        return UWBAPI_STATUS_NOT_INITIALIZED;
    }
    switch (paramId) {
    case TX_POWER_DIFF:
    case TX_POWER_DIFF_ANT_BOTTOM:
    case FREQ_DIFF:
    case ANTENNA_DELAY:
    case ANTENNA_DELAY_ANT_BOTTOM:
    case CURRENT_LIMIT_VALUE:
    case TEMP_COMPENS_FLAG:
    case TX_ADAPTIVE_POWER_CALC:
    case TX_ADAPTIVE_POWER_CALC_ANT_BOTTOM:
    case DDFS_TONE_VALUES:
    case DPD_TIMER_PENALTY_US:
    case WAKEUP_SENSOR_ENABLE:
    case SLOW_BLINK_INTERVAL:
    case TEMPERATURE_SOURCE:
    case THERMISTOR_RP:
    case TRIM_POWER_CTRL_PREAMBLE_10:
    case TRIM_POWER_CTRL_PREAMBLE_27:
    case TRIM_LOCK:
    case CUSTOM_LUTS_ENBL:
    case LUT_TEMP_RT_OFFSET:
    case LUT_TEMP_RT_SLOPE:
    case TRIM_PREAMBLE_10_27_PAYLOAD_PS_COEFFS_OVERRIDE:
    case MODULE_MAKER_ID:
    case GROUP_DELAY:
    case TRIMVALUES_GET_TEMPERATURE_X10:
        break;
    default:
        NXPLOG_UWBAPI_E("%s: Invalid calibration parameter ", __FUNCTION__);
        return UWBAPI_STATUS_INVALID_PARAM;
    }

    if (calibResp == NULL) {
        NXPLOG_UWBAPI_E("%s: calibResp is NULL", __FUNCTION__);
        return UWBAPI_STATUS_INVALID_PARAM;
    }
    pGetCalibrationCmd = uwbContext.snd_data;
    UCI_MSG_BLD_HDR0(pGetCalibrationCmd, UCI_MT_CMD, UCI_GID_PROPRIETARY);
    UCI_MSG_BLD_HDR1(pGetCalibrationCmd, EXT_UCI_MSG_GET_TRIM_VALUES_CMD);
    UWB_UINT8_TO_STREAM(pGetCalibrationCmd, 0x00);
    UWB_UINT8_TO_STREAM(pGetCalibrationCmd, payloadLen);
    UWB_UINT8_TO_STREAM(pGetCalibrationCmd, 1);
    UWB_UINT8_TO_STREAM(pGetCalibrationCmd, (uint8_t)paramId);

    status = sendRawUci(uwbContext.snd_data, (uint16_t)(payloadLen + UCI_MSG_HDR_SIZE));

    if (status == UWBAPI_STATUS_OK) {
        uint8_t *calibrationPtr = &uwbContext.rsp_data[UCI_RESPONSE_STATUS_OFFSET];

        if (uwbContext.rsp_len > sizeof(calibResp->calibValueOut)) {
            NXPLOG_UWBAPI_E("%s: Response data size is more than response buffer", __FUNCTION__);
            status = UWBAPI_STATUS_BUFFER_OVERFLOW;
        }
        else {
            /*
             * Exclude Calibration state.
             */
            calibResp->length =
                (uint16_t)(uwbContext.rsp_len - ((uint16_t)UCI_RESPONSE_PAYLOAD_OFFSET + sizeof(calibResp->rfu)));
            ++calibrationPtr;
            UWB_STREAM_TO_UINT8(calibResp->rfu, calibrationPtr);
            phOsalUwb_MemCopy(calibResp->calibValueOut, calibrationPtr, (uint8_t)calibResp->length);
            NXPLOG_UWBAPI_D("%s: Get Calibration successful", __FUNCTION__);
        }
    }
    else if (status == UWBAPI_STATUS_TIMEOUT) {
        NXPLOG_UWBAPI_E("%s: Get Calibration Command Timed Out", __FUNCTION__);
    }
    else {
        NXPLOG_UWBAPI_E("%s: Get Calibration value failed", __FUNCTION__);
    }
    if (status != UWBAPI_STATUS_OK)
        calibResp->length = 0;
    NXPLOG_UWBAPI_D("%s: Exit", __FUNCTION__);
    return status;
}

EXTERNC tUWBAPI_STATUS UwbApi_RadioConfigGetCrc(uint8_t radioConfigIndex, uint16_t *pCrc)
{
    tUWBAPI_STATUS status;
    uint8_t payloadLen            = 2; // One byte download sequence followed by Rx or Tx Radio config index
    uint8_t *pCommand             = NULL;
    edownloadSequence downloadSeq = kSR040_RadioCrc_GetCRC;
    uint8_t *pResponse            = NULL;
    uint16_t reponseLen           = 0;

    NXPLOG_UWBAPI_D("%s: Enter", __FUNCTION__);

    if (uwbContext.isUfaEnabled == FALSE) {
        NXPLOG_UWBAPI_E("%s: UWB device is not initialized", __FUNCTION__);
        return UWBAPI_STATUS_NOT_INITIALIZED;
    }

    if (pCrc == NULL) {
        NXPLOG_UWBAPI_E("%s: data is invalid", __FUNCTION__);
        return UWBAPI_STATUS_INVALID_PARAM;
    }

    pCommand = uwbContext.snd_data;
    UCI_MSG_BLD_HDR0(pCommand, UCI_MT_CMD, UCI_GID_PROPRIETARY);
    UCI_MSG_BLD_HDR1(pCommand, EXT_UCI_MSG_RADIO_CONFIG_DOWNLOAD_CMD);
    UWB_UINT8_TO_STREAM(pCommand, 0x00);
    UWB_UINT8_TO_STREAM(pCommand, payloadLen);
    UWB_UINT8_TO_STREAM(pCommand, downloadSeq);
    UWB_UINT8_TO_STREAM(pCommand, radioConfigIndex);

    status = sendRawUci(uwbContext.snd_data, UCI_MSG_HDR_SIZE + payloadLen);
    if (status == UWBAPI_STATUS_OK) {
        /* Need to exclude status in the response length */
        /* Shall receive status followed by CRC. Exclude the header part */
        pResponse  = &uwbContext.rsp_data[UCI_MSG_HDR_SIZE];
        reponseLen = (UCI_MSG_HDR_SIZE + sizeof(status) + sizeof(uint16_t));
        UWB_STREAM_TO_UINT8(status, pResponse);
        if (status == UWBAPI_STATUS_OK) {
            if (uwbContext.rsp_len > reponseLen) {
                NXPLOG_UWBAPI_E("%s: Response data size is more than response buffer", __FUNCTION__);
                status = UWBAPI_STATUS_BUFFER_OVERFLOW;
            }
            else {
                /* Fetch the CRC bytes */
                UWB_STREAM_TO_UINT16(*pCrc, pResponse);
            }
        }
    }
    else if (status == UWBAPI_STATUS_TIMEOUT) {
        NXPLOG_UWBAPI_E("%s: Radio Config Get CRC Command Timed Out", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_HPD_WAKEUP) {
        NXPLOG_UWBAPI_W("%s: Device Woken up from HPD", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_LOW_POWER_ERROR) {
        NXPLOG_UWBAPI_E("%s: Device having very low battery power", __FUNCTION__);
    }
    else {
        NXPLOG_UWBAPI_W("%s: Ensure all radio settings are up loaded ", __FUNCTION__);
    }

    NXPLOG_UWBAPI_D("%s: Exit", __FUNCTION__);
    return status;
}

EXTERNC tUWBAPI_STATUS UwbApi_RadioConfigGetAllCrc(uint16_t *pCrc)
{
    tUWBAPI_STATUS status;
    uint8_t payloadLen            = 1 + 1; // One byte download sequence + RFU
    uint8_t *pCommand             = NULL;
    edownloadSequence downloadSeq = kSR040_RadioCrc_GetAllCRC;
    uint8_t *pResponse            = NULL;
    uint16_t reponseLen           = 0;

    NXPLOG_UWBAPI_D("%s: Enter", __FUNCTION__);

    if (uwbContext.isUfaEnabled == FALSE) {
        NXPLOG_UWBAPI_E("%s: UWB device is not initialized", __FUNCTION__);
        return UWBAPI_STATUS_NOT_INITIALIZED;
    }

    if (pCrc == NULL) {
        NXPLOG_UWBAPI_E("%s: data is invalid", __FUNCTION__);
        return UWBAPI_STATUS_INVALID_PARAM;
    }

    pCommand = uwbContext.snd_data;
    UCI_MSG_BLD_HDR0(pCommand, UCI_MT_CMD, UCI_GID_PROPRIETARY);
    UCI_MSG_BLD_HDR1(pCommand, EXT_UCI_MSG_RADIO_CONFIG_DOWNLOAD_CMD);
    UWB_UINT8_TO_STREAM(pCommand, 0x00);
    UWB_UINT8_TO_STREAM(pCommand, payloadLen);
    UWB_UINT8_TO_STREAM(pCommand, downloadSeq);
    UWB_UINT8_TO_STREAM(pCommand, 0); // RFU

    status = sendRawUci(uwbContext.snd_data, UCI_MSG_HDR_SIZE + payloadLen);
    if (status == UWBAPI_STATUS_OK) {
        /* Need to exclude status in the response length */
        /* Shall receive status followed by CRC. Exclude the header part */
        pResponse  = &uwbContext.rsp_data[UCI_MSG_HDR_SIZE];
        reponseLen = (UCI_MSG_HDR_SIZE + sizeof(status) + sizeof(uint16_t));
        UWB_STREAM_TO_UINT8(status, pResponse);
        if (status == UWBAPI_STATUS_OK) {
            if (uwbContext.rsp_len > reponseLen) {
                NXPLOG_UWBAPI_E("%s: Response data size is more than response buffer", __FUNCTION__);
                status = UWBAPI_STATUS_BUFFER_OVERFLOW;
            }
            else {
                /* Fetch the CRC bytes */
                UWB_STREAM_TO_UINT16(*pCrc, pResponse);
            }
        }
    }
    else if (status == UWBAPI_STATUS_TIMEOUT) {
        NXPLOG_UWBAPI_E("%s: Radio Config Get CRC Command Timed Out", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_HPD_WAKEUP) {
        NXPLOG_UWBAPI_W("%s: Device Woken up from HPD", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_LOW_POWER_ERROR) {
        NXPLOG_UWBAPI_E("%s: Device having very low battery power", __FUNCTION__);
    }
    else {
        NXPLOG_UWBAPI_W("%s:  Ensure all radio settings are up loaded ", __FUNCTION__);
    }

    NXPLOG_UWBAPI_D("%s: Exit", __FUNCTION__);
    return status;
}

EXTERNC tUWBAPI_STATUS RadioConfig_CheckCrc(void)
{
    const RadioConfigCrcTable_t radioConfigCrcTable[] = SR040_RADIO_CONFIG_CRC_full;
    int loopIndex;
    const int noOfIndexes = sizeof(radioConfigCrcTable) / sizeof(radioConfigCrcTable[0]);
    tUWBAPI_STATUS status;
    uint16_t expectedCrc;

    /* Check the crc's of all the blocks are correct or not */
    for (loopIndex = 0; loopIndex < noOfIndexes; ++loopIndex) {
    retry:
        status = UwbApi_RadioConfigGetCrc(radioConfigCrcTable[loopIndex].index, &expectedCrc);
        if (UWBAPI_STATUS_HPD_WAKEUP == status) {
            goto retry;
        }
        if (status != UWBAPI_STATUS_OK) {
            NXPLOG_UWBAPI_E("UwbApi_RadioConfigGetCrc Failed");
            goto exit;
        }

        if (expectedCrc != radioConfigCrcTable[loopIndex].crc) {
            NXPLOG_UWBAPI_E("CRC Check Failed for Index %d", radioConfigCrcTable[loopIndex].index);
            status = UWBAPI_STATUS_FAILED;
            goto exit;
        }
    }
exit:
    return status;
}

EXTERNC tUWBAPI_STATUS UwbApi_Get_Lut_Crc(eGetLutCrc xtalid, uint16_t *pCrc)
{
    tUWBAPI_STATUS status;
    uint8_t payloadLen  = 1;
    uint8_t *pCommand   = NULL;
    uint8_t *pResponse  = NULL;
    uint16_t reponseLen = 0;
    NXPLOG_UWBAPI_D("%s: Enter", __FUNCTION__);

    if (uwbContext.isUfaEnabled == FALSE) {
        NXPLOG_UWBAPI_E("%s: UWB device is not initialized", __FUNCTION__);
        return UWBAPI_STATUS_NOT_INITIALIZED;
    }

    if (pCrc == NULL || xtalid > kSR040_Thermister_LUT_CRC) {
        NXPLOG_UWBAPI_E("%s: data is invalid", __FUNCTION__);
        return UWBAPI_STATUS_INVALID_PARAM;
    }

    pCommand = uwbContext.snd_data;
    UCI_MSG_BLD_HDR0(pCommand, UCI_MT_CMD, UCI_GID_PROPRIETARY);
    UCI_MSG_BLD_HDR1(pCommand, EXT_UCI_MSG_GET_LUT_CRC);
    UWB_UINT8_TO_STREAM(pCommand, 0x00);
    UWB_UINT8_TO_STREAM(pCommand, payloadLen);
    UWB_UINT8_TO_STREAM(pCommand, xtalid);
    status = sendRawUci(uwbContext.snd_data, UCI_MSG_HDR_SIZE + payloadLen);
    if (status == UWBAPI_STATUS_OK) {
        pResponse = &uwbContext.rsp_data[UCI_MSG_HDR_SIZE];
        reponseLen =
            (UCI_MSG_HDR_SIZE + sizeof(status) + LUT_TLV_COUNT_LEN + LUT_TLV_SEL_LEN + LUT_CRC_LEN + sizeof(uint16_t));
        UWB_STREAM_TO_UINT8(status, pResponse);
        if (uwbContext.rsp_len > reponseLen) {
            NXPLOG_UWBAPI_E("%s: Response data size is more than response buffer", __FUNCTION__);
            status = UWBAPI_STATUS_BUFFER_OVERFLOW;
        }
        else {
            /* Fetch the CRC bytes */
            /*skip lenght  part*/
            pResponse = pResponse + LUT_TLV_COUNT_LEN + LUT_TLV_SEL_LEN + LUT_CRC_LEN;
            UWB_STREAM_TO_UINT16(*pCrc, pResponse);
        }
    }
    else if (status == UWBAPI_STATUS_TIMEOUT) {
        NXPLOG_UWBAPI_E("%s: Command Timed Out", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_HPD_WAKEUP) {
        NXPLOG_UWBAPI_W("%s: Device Woken up from HPD", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_LOW_POWER_ERROR) {
        NXPLOG_UWBAPI_E("%s: Device having very low battery power", __FUNCTION__);
    }
    else {
        NXPLOG_UWBAPI_E("%s: Get XTAL_LUT_GET_CRC Command failed", __FUNCTION__);
    }
    NXPLOG_UWBAPI_D("%s: Exit", __FUNCTION__);
    return status;
}

tUWBAPI_STATUS UwbApi_SetDefaultCoreConfigs()
{
    return setDefaultCoreConfigs();
}

EXTERNC tUWBAPI_STATUS UwbApi_Set_Bypass_Current_Limiter(bool BypassMode)
{
    tUWBAPI_STATUS status;
    uint8_t payloadLen = 1;
    uint8_t *pCommand  = NULL;
    uint8_t *pResponse = NULL;
    NXPLOG_UWBAPI_D("%s: Enter", __FUNCTION__);

    if (uwbContext.isUfaEnabled == FALSE) {
        NXPLOG_UWBAPI_E("%s: UWB device is not initialized", __FUNCTION__);
        return UWBAPI_STATUS_NOT_INITIALIZED;
    }

    pCommand = uwbContext.snd_data;
    UCI_MSG_BLD_HDR0(pCommand, UCI_MT_CMD, UCI_GID_PROPRIETARY);
    UCI_MSG_BLD_HDR1(pCommand, EXT_UCI_MSG_BYPASS_CURRENT_LIMITER_CMD);
    UWB_UINT8_TO_STREAM(pCommand, 0x00);
    UWB_UINT8_TO_STREAM(pCommand, payloadLen);
    UWB_UINT8_TO_STREAM(pCommand, BypassMode);
    status = sendRawUci(uwbContext.snd_data, UCI_MSG_HDR_SIZE + payloadLen);
    if (status == UWBAPI_STATUS_OK) {
        pResponse = &uwbContext.rsp_data[UCI_MSG_HDR_SIZE];
        UWB_STREAM_TO_UINT8(status, pResponse);
        NXPLOG_UWBAPI_I("%d\n", status);
    }
    else if (status == UWBAPI_STATUS_TIMEOUT) {
        NXPLOG_UWBAPI_E("%s: Command Timed Out", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_HPD_WAKEUP) {
        NXPLOG_UWBAPI_W("%s: Device Woken up from HPD", __FUNCTION__);
    }
    else if (status == UWBAPI_STATUS_LOW_POWER_ERROR) {
        NXPLOG_UWBAPI_E("%s: Device having very low battery power", __FUNCTION__);
    }
    else {
        NXPLOG_UWBAPI_E("%s: UwbApi_Set_Bypass_Current_Limiter Command failed", __FUNCTION__);
    }
    NXPLOG_UWBAPI_D("%s: Exit", __FUNCTION__);
    return status;
}

tUWBAPI_STATUS UwbApi_Set_Radio_Configs_Full(phRadioConfigInfo_t *radioconfigs)
{
    tUWBAPI_STATUS status;
    uint16_t outCRC = 0;
    NXPLOG_UWBAPI_D("%s: Enter", __FUNCTION__);
    /** This is used as start index for both Tx and Rx*/
    uint8_t radio_cfg_start_index = 0;
    if (uwbContext.isUfaEnabled == FALSE) {
        NXPLOG_UWBAPI_E("%s: UWB device is not initialized", __FUNCTION__);
        return UWBAPI_STATUS_NOT_INITIALIZED;
    }

    if (radioconfigs == NULL) {
        NXPLOG_UWBAPI_E("%s: data is invalid", __FUNCTION__);
        return UWBAPI_STATUS_INVALID_PARAM;
    }

    if (radioconfigs->radio_settings_table_size != MAX_RADIO_CONFIG_SIZE) {
        NXPLOG_UWBAPI_E("%s: Input length is not sufficient with requirement ", __FUNCTION__);
        return UWBAPI_STATUS_INVALID_PARAM;
    }
    /*
     *  1: Check the Overall CRC if its matches in case of safe  update skip the update.
     *  2: During safe update if CRC is mismatches then update the Radio configs full and check the CRC.
     *  3: During force update update the full radio configs and check the CRC.
     */
    if (!radioconfigs->force_update) {
        status = UwbApi_RadioConfigGetAllCrc(&outCRC);
        if (status == UWBAPI_STATUS_OK) {
            if (SR040_RADIO_CFG_FULL_CRC == outCRC) {
                NXPLOG_UWBAPI_I("CRC is matching after Radio settings Update");
                goto exit;
            }
        }
        else {
            NXPLOG_UWBAPI_W("Updating the Radio configs");
        }
    }
    /* Flash RX radio settings */
    while (radio_cfg_start_index < RX_RADIO_CONFIG_END_INDEX) {
        status = UpdateRadioSettings(radio_cfg_start_index,
            radioconfigs->radio_settings_table,
            RX_RADIO_SETTING_SIZE,
            radioconfigs->radio_settings_crc[radio_cfg_start_index]);
        if (status != UWBAPI_STATUS_OK) {
            NXPLOG_UWBAPI_E("RadioSettings Failed while updating RX at Index %d", radio_cfg_start_index);
            goto exit;
        }
        radioconfigs->radio_settings_table += RX_RADIO_SETTING_SIZE;
        radio_cfg_start_index++;
    }
    /* Flash TX radio settings */
    while (radio_cfg_start_index < TX_RADIO_CONFIG_END_INDEX) {
        status = UpdateRadioSettings(radio_cfg_start_index,
            radioconfigs->radio_settings_table,
            TX_RADIO_SETTING_SIZE,
            radioconfigs->radio_settings_crc[radio_cfg_start_index]);
        if (status != UWBAPI_STATUS_OK) {
            NXPLOG_UWBAPI_E("RadioSettings Failed while updating TX at Index %d", radio_cfg_start_index);
            goto exit;
        }
        radioconfigs->radio_settings_table += TX_RADIO_SETTING_SIZE;
        radio_cfg_start_index++;
    }

    /*
     *  1: Check the Overall CRC if its matches
     *  2: This is to ensure Radio configs are flashed Properly.
     */

    status = UwbApi_RadioConfigGetAllCrc(&outCRC);
    if (status == UWBAPI_STATUS_OK) {
        if (SR040_RADIO_CFG_FULL_CRC == outCRC) {
            NXPLOG_UWBAPI_I("CRC is matching after Radio settings Update");
            goto exit;
        }
        else {
            NXPLOG_UWBAPI_E("CRC is not-matching after Radio settings Update ");
            status = UWBAPI_STATUS_FAILED;
            goto exit;
        }
    }
    else {
        NXPLOG_UWBAPI_E("Radion configuration CRC is Failed ");
    }

exit:
    NXPLOG_UWBAPI_D("%s: Exit", __FUNCTION__);
    return status;
}

tUWBAPI_STATUS UwbApi_ConfigureData_iOS(uint8_t *pShareableData,
    uint16_t ShareableDataLength,
    phUwbProfileInfo_t *pProfileInfo,
    uint8_t noOfAppParams,
    const UWB_AppParams_List_t *AppParams_List)
{
    NXPLOG_UWBAPI_D("%s: enter", __FUNCTION__);
    tUWBAPI_STATUS status;

    if (pProfileInfo == NULL) {
        NXPLOG_UWBAPI_E("%s: pProfileInfo is invalid", __FUNCTION__);
        status = UWBAPI_STATUS_INVALID_PARAM;
        goto exit;
    }
    if (pShareableData == NULL) {
        NXPLOG_UWBAPI_E("%s: pShareableData is invalid", __FUNCTION__);
        status = UWBAPI_STATUS_INVALID_PARAM;
        goto exit;
    }

    if ((ShareableDataLength != TOTAL_PROFILE_BLOB_SIZE_v1_1) &&
        (ShareableDataLength != TOTAL_PROFILE_BLOB_SIZE_v1_0)) {
        NXPLOG_UWBAPI_E("%s: profile blob size should be %d or %d bytes",
            __FUNCTION__,
            TOTAL_PROFILE_BLOB_SIZE_v1_0,
            TOTAL_PROFILE_BLOB_SIZE_v1_1);
        status = UWBAPI_STATUS_INVALID_PARAM;
        goto exit;
    }

    pProfileInfo->profileId = kUWB_Profile_1;

    status = UwbApi_SetProfileParams(pShareableData, ShareableDataLength, pProfileInfo);
    if (status != UWBAPI_STATUS_OK) {
        NXPLOG_UWBAPI_E("UwbApi_SetProfileParams failed");
        goto exit;
    }

    if ((noOfAppParams != 0) && (AppParams_List != NULL)) {
        status = UwbApi_SetAppConfigMultipleParams(pProfileInfo->sessionHandle, noOfAppParams, AppParams_List);
        if (status != UWBAPI_STATUS_OK) {
            NXPLOG_UWBAPI_E("UwbApi_SetAppConfigMultipleParams failed");
            goto exit;
        }
    }

    status = UwbApi_StartRangingSession(pProfileInfo->sessionHandle);
    if (status != UWBAPI_STATUS_OK) {
        NXPLOG_UWBAPI_E("UwbApi_StartRangingSession() Failed");
        goto exit;
    }
exit:
    NXPLOG_UWBAPI_D("%s: exit status %d", __FUNCTION__, status);
    return status;
}

tUWBAPI_STATUS UwbApi_ConfigureData_Android(uint8_t *pUwbPhoneConfigData,
    uint16_t UwbPhoneConfigDataLen,
    phUwbProfileInfo_t *pProfileInfo,
    uint8_t noOfAppParams,
    const UWB_AppParams_List_t *AppParams_List)
{
    NXPLOG_UWBAPI_D("%s: enter", __FUNCTION__);
    tUWBAPI_STATUS status;
    uint32_t sessionHandle = 0;

    uint8_t stsStatic[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
    uint8_t vendorId[]  = {0x08, 0x07};

    phRangingParams_t inRangingParams = {0};
    UwbPhoneConfigData_t UwbPhoneConfig;

    if (pUwbPhoneConfigData == NULL || pProfileInfo == NULL) {
        NXPLOG_UWBAPI_E("%s: Phone Config Data or profile info is invalid", __FUNCTION__);
        status = UWBAPI_STATUS_INVALID_PARAM;
        goto exit;
    }

    if (UwbPhoneConfigDataLen == SHAREABLE_DATA_HEADER_LENGTH_ANDROID) {
        serializeUwbPhoneConfigData(&UwbPhoneConfig, pUwbPhoneConfigData);
    }
    else {
        NXPLOG_UWBAPI_E("%s: Phone Config Data length is invalid : %d", __FUNCTION__, UwbPhoneConfigDataLen);
        status = UWBAPI_STATUS_INVALID_PARAM;
        goto exit;
    }

    status = UwbApi_SessionInit(UwbPhoneConfig.session_id, UWBD_RANGING_SESSION, &sessionHandle);
    if (status != UWBAPI_STATUS_OK) {
        NXPLOG_UWBAPI_E("UwbApi_SessionInit() Failed");
        goto exit;
    }

    pProfileInfo->sessionHandle = sessionHandle;

    switch (UwbPhoneConfig.profile_id) {
    case UWB_CONFIG_ID_1: {
        // Add unicast
        inRangingParams.multiNodeMode = kUWB_MultiNodeMode_UniCast;

        const UWB_AppParams_List_t SetAppParamsList[] = {
            UWB_SET_APP_PARAM_VALUE(RANGING_DURATION, 240),
            UWB_SET_APP_PARAM_VALUE(SLOT_DURATION, 2400),
            UWB_SET_APP_PARAM_VALUE(SLOTS_PER_RR, 6),
            UWB_SET_APP_PARAM_ARRAY(
                STATIC_STS_IV, &stsStatic[0], sizeof(stsStatic)),               // Android shows [1, 2, 3, 4, 5, 6]
            UWB_SET_APP_PARAM_ARRAY(VENDOR_ID, &vendorId[0], sizeof(vendorId)), // Android shows [7, 8]
            UWB_SET_APP_PARAM_VALUE(PREAMBLE_CODE_INDEX, UwbPhoneConfig.preamble_id),
            UWB_SET_APP_PARAM_VALUE(CHANNEL_NUMBER, UwbPhoneConfig.channel_number),
            UWB_SET_APP_PARAM_VALUE(NO_OF_CONTROLEES, 1),
            UWB_SET_APP_PARAM_ARRAY(DST_MAC_ADDRESS, UwbPhoneConfig.phone_mac_address, MAC_SHORT_ADD_LEN),
        };

        status = UwbApi_SetAppConfigMultipleParams(
            pProfileInfo->sessionHandle, sizeof(SetAppParamsList) / sizeof(SetAppParamsList[0]), &SetAppParamsList[0]);
        if (status != UWBAPI_STATUS_OK) {
            NXPLOG_UWBAPI_E("UwbApi_SetAppConfigMultipleParams() Failed");
            goto exit;
        }
    } break;

    default: {
        NXPLOG_UWBAPI_E("Profile ID not supported");
        status = UWBAPI_STATUS_FAILED;
        goto exit;
    } break;
    }

    switch (UwbPhoneConfig.device_ranging_role) {
    case UWB_DEVICE_CONTROLLER: {
        inRangingParams.deviceRole = kUWB_DeviceRole_Initiator;
        inRangingParams.deviceType = kUWB_DeviceType_Controller;
    } break;

    case UWB_DEVICE_CONTROLEE: {
        inRangingParams.deviceRole = kUWB_DeviceRole_Responder;
        inRangingParams.deviceType = kUWB_DeviceType_Controlee;
    } break;

    default: {
        NXPLOG_UWBAPI_E("Role not supported");
        status = UWBAPI_STATUS_FAILED;
        goto exit;
    } break;
    }

    inRangingParams.deviceMacAddr[0] = pProfileInfo->mac_addr[0];
    inRangingParams.deviceMacAddr[1] = pProfileInfo->mac_addr[1];

    inRangingParams.scheduledMode     = kUWB_ScheduledMode_TimeScheduled;
    inRangingParams.rangingRoundUsage = kUWB_RangingRoundUsage_DS_TWR;

    status = UwbApi_SetRangingParams(pProfileInfo->sessionHandle, &inRangingParams);
    if (status != UWBAPI_STATUS_OK) {
        NXPLOG_UWBAPI_E("UwbApi_SetRangingParams() Failed");
        goto exit;
    }

    if ((noOfAppParams != 0) && (AppParams_List != NULL)) {
        status = UwbApi_SetAppConfigMultipleParams(pProfileInfo->sessionHandle, noOfAppParams, AppParams_List);
        if (status != UWBAPI_STATUS_OK) {
            NXPLOG_UWBAPI_E("UwbApi_SetAppConfigMultipleParams failed");
            goto exit;
        }
    }

    status = UwbApi_StartRangingSession(pProfileInfo->sessionHandle);
    if (status != UWBAPI_STATUS_OK) {
        NXPLOG_UWBAPI_E("UwbApi_StartRangingSession() Failed");
        goto exit;
    }
exit:
    NXPLOG_UWBAPI_D("%s: exit status %d", __FUNCTION__, status);
    return status;
}
